#ifndef ABC_CONTEXT_H
#define ABC_CONTEXT_H
#include <vector>
#include <variant>
#include <string>
#include <memory>
#include <set>
#include "c/abckit.h"
#include <algorithm>
#include "metadata.h"

struct AbcPath
{
    std::string module = "";
    std::string package = "";
    std::string namespaces = "";
    std::string originModulePath = "";
};

template <typename T>
struct AbcNode;

struct AbcFunc
{
    std::string name;
    AbckitCoreFunction *func;
    AbcFuncType type;
    std::shared_ptr<AbcNode<AbckitCoreModule>> parentModule;
    std::shared_ptr<AbcNode<AbckitCoreNamespace>> parentNamespace;
    std::shared_ptr<AbcNode<AbckitCoreClass>> parentClass;
    std::set<std::shared_ptr<AbcFunc>> anonymousFuncs;
    bool isTopLevel = false;
    bool hasAnnotation = false;
    bool isStatic = false;
};

template <typename T>
struct AbcNode
{
    AbcNodeType type;
    std::string name;
    std::shared_ptr<AbcPath> path;
    T *curNode;
    std::shared_ptr<AbcNode<AbckitCoreNamespace>> parentNS;
    std::shared_ptr<AbcNode<AbckitCoreModule>> parentModule;
    std::vector<std::shared_ptr<AbcFunc>> methods;
};

class AbcContext
{
public:
    std::string abc_path;
    AbckitFile *file;
    std::vector<std::shared_ptr<AbcNode<AbckitCoreModule>>> moduleNodes;
    std::vector<std::shared_ptr<AbcNode<AbckitCoreNamespace>>> namespaceNodes;
    std::vector<std::shared_ptr<AbcNode<AbckitCoreClass>>> classNodes;
    std::vector<std::shared_ptr<AbcFunc>> methods;
    ~AbcContext();
};

AbcContext const *AbcContextApiImpl(std::string abc_path);

#endif // ABC_CONTEXT_H